/**
 * 事务代理工厂类，用于创建带有事务管理功能的代理对象
 */
package com.jms.framework.jdbc.transaction.proxy;

import com.jms.framework.jdbc.transaction.adaper.TransactionManagementAdapter;
import com.jms.framework.jdbc.transaction.annotation.Transaction;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TransactionProxyFactory {

    /**
     * 使用JDK动态代理获取代理对象
     *
     * @param target 目标对象
     * @param <T>    目标对象类型
     * @return 代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T getProxy(T target) {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new TransactionInvocationHandler(target));
    }

    /**
     * 使用JDK动态代理获取代理对象，指定接口
     *
     * @param target 目标对象
     * @param interfaces 目标对象实现的接口
     * @param <T>    目标对象类型
     * @return 代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T getProxy(T target, Class<?>[] interfaces) {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), interfaces, new TransactionInvocationHandler(target));
    }

    /**
     * 使用CGLIB获取代理对象
     *
     * @param target 目标对象
     * @param <T>    目标对象类型
     * @return 代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T getCglibProxy(T target) {
        return (T) Enhancer.create(target.getClass(), new TransactionMethodInterceptor());
    }

    /**
     * 事务处理的InvocationHandler实现类
     */
    private static class TransactionInvocationHandler implements InvocationHandler {
        private final Object target;

        public TransactionInvocationHandler(Object target) {
            this.target = target;
        }

        /**
         * 方法调用处理，带有事务管理
         *
         * @param proxy 代理对象
         * @param method 被调用的方法
         * @param args 方法参数
         * @return 方法返回值
         * @throws Throwable 方法调用过程中抛出的异常
         */
        @Override
        public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable {
            if (method.isAnnotationPresent(Transaction.class)) {
                Object res = null;
                try {
                    TransactionManagementAdapter.getInstance().begin();
                    res = method.invoke(target, args);
                    TransactionManagementAdapter.getInstance().commit();
                } catch (Exception e) {
                    TransactionManagementAdapter.getInstance().rollback();
                } finally {
                    TransactionManagementAdapter.getInstance().close();
                }
                return res;
            } else {
                return method.invoke(target, args);
            }
        }
    }

    /**
     * 事务处理的MethodInterceptor实现类
     */
    private static class TransactionMethodInterceptor implements MethodInterceptor {
        /**
         * 方法拦截处理，带有事务管理
         *
         * @param o 被代理的对象
         * @param method 被拦截的方法
         * @param objects 方法参数
         * @param methodProxy 方法代理对象
         * @return 方法返回值
         * @throws Throwable 方法调用过程中抛出的异常
         */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            if (method.isAnnotationPresent(Transaction.class)) {
                Object res = null;
                try {
                    TransactionManagementAdapter.getInstance().begin();
                    res = methodProxy.invokeSuper(o, objects);
                    TransactionManagementAdapter.getInstance().commit();
                } catch (Exception e) {
                    TransactionManagementAdapter.getInstance().rollback();
                } finally {
                    TransactionManagementAdapter.getInstance().close();
                }
                return res;
            } else {
                return methodProxy.invokeSuper(o, objects);
            }
        }
    }
}
